/* 
 * File:   pthread.hpp
 * Author: yuri
 *
 * Created on February 6, 2011, 11:55 PM
 */

#ifndef POSIX_WRAP_PTHREAD_HPP_____
#define	POSIX_WRAP_PTHREAD_HPP_____

#include "config.hpp"
#include "time.hpp"
#include "sched.hpp"
#include <pthread.h>

// *****************************************************************************
// * Begin PosixWrap namespace
// *****************************************************************************
BEGIN_PSX_NAMESPACE

// *****************************************************************************
// * class ThreadAttr
// *****************************************************************************
class ThreadAttr
{
  public:
    ThreadAttr();
    ~ThreadAttr();

    //PTHREAD_CREATE_DETACHED or PTHREAD_CREATE_JOINABLE
    ThreadAttr& setDetachState(int value);
    int getDetachState() const;

    ThreadAttr& setGuardSize(size_t value);
    size_t getGuardSize() const;

    //values - PTHREAD_INHERIT_SCHED or PTHREAD_EXPLICIT_SCHED
    ThreadAttr& setInheritSched(int value);
    int getInheritSched() const;

    ThreadAttr& setSchedParam(const SchedParam& value);
    void getSchedParam(SchedParam& value) const;

    ThreadAttr& setSchedPolicy(int value);
    int getSchedPolicy() const;

    //values : PTHREAD_SCOPE_SYSTEM, PTHREAD_SCOPE_PROCESS
    ThreadAttr& setScope(int contentionscope);
    int getScope() const;

    ThreadAttr& setStack(void* address, size_t size);
    void getStack(void*& address, size_t& size) const;

    ThreadAttr& setStackSize(size_t value);
    size_t getStackSize() const;

    ::pthread_attr_t& getThreadAttr();
    const ::pthread_attr_t& getThreadAttr() const;

  private:
    ::pthread_attr_t    data_;
};

// *****************************************************************************
// * class Thread
// *****************************************************************************
class Thread
{
  public:
    class ThreadFunction
    {
      public:
        virtual void* thread() = 0;
    };

    explicit Thread(ThreadFunction& fun);
    Thread(const ThreadAttr& attributes, ThreadFunction& fun);
    ~Thread();
    
    void cancel();
    void detach();
    //void kill(int sig);
    
    static void* join(Thread& thread);
    
  private:
    static void* thread_function(void* param);
    pthread_t thread_;
};

// *****************************************************************************
// * class MutexAttr
// *****************************************************************************
class MutexAttr
{
  public:
    MutexAttr();
    ~MutexAttr();
    
    MutexAttr& setPrioceiling(int value);
    int getPrioceiling() const;

    MutexAttr& setProtocol(int value);
    int getProtocol() const;

    MutexAttr& setShared(int value);
    int getShared() const;

    MutexAttr& setRobust(int value);
    int getRobust() const;

    MutexAttr& setType(int value);
    int getType() const;
    
    pthread_mutexattr_t& getMutexAttr();
    const pthread_mutexattr_t& getMutexAttr() const;
    
  private:
    pthread_mutexattr_t data_;
};

// *****************************************************************************
// * class Mutex
// *****************************************************************************
class Mutex
{
  public:
    Mutex();
    explicit Mutex(const MutexAttr& attributes);
    ~Mutex();

    void lock();
    bool tryLock();
    void unlock();
    
    void timedLock(const TimeSpec& abs_time);
    
    int setPrioCeiling(int prioceiling);
    int getPrioCeiling() const;
  private:
    pthread_mutex_t data_;
};

// *****************************************************************************
// * End PosixWrap namespace
// *****************************************************************************
END_PSX_NAMESPACE

// *****************************************************************************
// *****************************************************************************
// * INLINE FUNCTIONS
// *****************************************************************************
// *****************************************************************************

// *****************************************************************************
// * Begin PosixWrap namespace
// *****************************************************************************
BEGIN_PSX_NAMESPACE


// *****************************************************************************
// * End PosixWrap namespace
// *****************************************************************************
END_PSX_NAMESPACE

#endif	//#ifndef POSIX_WRAP_PTHREAD_HPP_____
